package com.c2b.algorithm.leetcode.base;

/**
 * <a href='https://leetcode.cn/problems/next-permutation/description/'>下一个排列(Next Permutation)</a>
 * <p>整数数组的一个 排列  就是将其所有成员以序列或线性顺序排列。</p>
 * <p>例如，arr = [1,2,3] ，以下这些都可以视作 arr 的排列：[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。</p>
 * <p>
 * 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地，如果数组的所有排列根据其字典顺序从小到大排列在一个容器中，那么数组的 下一个排列 就是在这个有序容器中排在它后面的那个排列。如果不存在下一个更大的排列，那么这个数组必须重排为字典序最小的排列（即，其元素按升序排列）。
 *     <ul>
 *         <li>例如，arr = [1,2,3] 的下一个排列是 [1,3,2] 。</li>
 *         <li>类似地，arr = [2,3,1] 的下一个排列是 [3,1,2] 。</li>
 *         <li>而 arr = [3,2,1] 的下一个排列是 [1,2,3] ，因为 [3,2,1] 不存在一个字典序更大的排列。</li>
 *     </ul>
 *     给你一个整数数组 nums ，找出 nums 的下一个排列。
 * </p>
 * <p>必须 原地 修改，只允许使用额外常数空间。</p>
 * <p>
 * <b>示例：</b>
 * <pre>
 * 示例 1：
 *      输入：nums = [1,2,3]
 *      输出：[1,3,2]
 *
 * 示例 2：
 *      输入：nums = [3,2,1]
 *      输出：[1,2,3]
 *
 * 示例 3：
 *      输入：nums = [1,1,5]
 *      输出：[1,5,1]
 *     </pre>
 * </p>
 * <p>
 * <b>提示：</b>
 *     <ul>
 *         <li>1 <= nums.length <= 100</li>
 *         <li>0 <= nums[i] <= 100</li>
 *     </ul>
 * </p>
 *
 * @author c2b
 * @since 2023/10/30 14:31
 */
public class LC0031NextPermutation_M {

    static class Solution {

        public void nextPermutation(int[] nums) {
            if (nums.length <= 1) {
                return;
            }
            int firstIndex = nums.length - 2;
            // 从后往前找到第一个相邻的降序序列。如果存在：firstIndex>=0；如果不存在 firstIndex =-1
            // ==> 目的是：找到比当前数大的数
            while (firstIndex >= 0 && nums[firstIndex] >= nums[firstIndex + 1]) {
                firstIndex--;
            }
            // 说明存在降序序列。判断在一次查找过程中是否存在更小的值
            // ==> 目的是：找到比当前数大的数的最小数
            if (firstIndex >= 0) {
                int secondIndex = nums.length - 1;
                while (secondIndex >= 0 && nums[firstIndex] >= nums[secondIndex]) {
                    secondIndex--;
                }
                // 交换
                swap(nums, firstIndex, secondIndex);
            }
            // 再从后往前找，将这个过程中升序序列对调换位置。例如：126543 --> 136542 --> 132456
            reverse(nums, firstIndex + 1);

        }

        public void reverse(int[] nums, int start) {
            int left = start;
            int right = nums.length - 1;
            while (left < right) {
                swap(nums, left, right);
                left++;
                right--;
            }
        }

        public void swap(int[] nums, int i, int j) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
        }


    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        solution.nextPermutation(new int[]{1, 2, 3});
        solution.nextPermutation(new int[]{3, 2, 1});
        solution.nextPermutation(new int[]{1, 1, 3});
    }
}
